<?php

class RssModel extends Model 
{
    /**
     * Количество rss-потоков на странице в админке
     *
     */
    const ADMIN_RSS_ON_PAGE = 30;
    
    protected $table = 'rss';
    
    protected $last_count = 0;
    
    /**
     * Добавить rss-ленту в список
     *
     * @param string $url
     * @param int $status
     * @return int
     */
    public function add($url, $status = Rss::STATUS_NEW)
    {
        return $this->prepare("INSERT INTO {$this->table} (`url`, `status`, `date_added`, `date_last_update`) VALUES (s:url, i:status, NOW(), NOW())")
                    ->query(array('url' => $url, 'status' => intval($status)))->getInsertId();
    }
    
    /**
     * Удалить rss-ленту из списка
     *
     * @param int $id
     * @return bool
     */
    public function delete($id)
    {
        return (bool)$this->prepare("DELETE FROM {$this->table} WHERE id = i:id")->exec(array('id' => $id));
    }
    
    /**
     * Обновить запись об RSS-потоке
     *
     * @param Rss $rss
     * @return bool
     */
    public function edit(Rss $rss)
    {
        $data = array(
            'id' => $rss->getId(),
            'url' => $rss->getUrl(),
            'status' => $rss->getStatus(),
        );
        $sql = 'UPDATE `'.$this->table.'` SET `url` = s:url, `status` = i:status WHERE `id` = i:id';
        return (bool)$this->prepare($sql)->exec($data);
    }
    
    /**
     * Получить запись по идентификатору
     *
     * @param int $id
     * @return Rss
     */
    public function get($id)
    {
        $row = $this->getQueryConstructor()->findById(intval($id))->fetch();
        
        if ($row) {
            return new Rss($row['id'], $row['url'], $row['status'], $row['date_added'], $row['date_last_update']);
        }
        return null;
    }
    
    /**
     * Получает id ленты по урлу
     * @param $url
     */
    public function getIdByURL($url)
    {
        return $this->getQueryConstructor()->filter('url', $url)->find()->fetchField('id');
    }
    
    /**
     * Получить список записей с указанным/указанными статусами
     *
     * @param int | array $status
     * @return array(id => Rss)
     */
    public function getList($page = 1, $limit = self::ADMIN_RSS_ON_PAGE, $status = null, $filter = array(), $order = array('field' => 'date_added', 'by' => 'DESC'))
    {
        $offset = (intval($page) > 0 ? intval($page) - 1 : 0) * $limit;
        
        if (!is_null($status)) {
            $c = $this->getQueryConstructor()->filter('status', $status);
        } else {
            $c = $this->getQueryConstructor();
        }
        
        foreach ((array)$filter as $field => $value) {
            $c->filter($field, $value);
        }
        
        $this->last_count = $c->count();
        $list = $c->order($order['field'], $order['by'])->limit($offset, $limit)->find()->fetchAll('id');
        
        $rss_list = array();
        foreach ((array)$list as $id => $row) {
            $rss_list[$id] = new Rss($row['id'], $row['url'], $row['status'], $row['date_added'], $row['date_last_update']);
        }
        
        return $rss_list;
    }
    
    public function getTotalCount()
    {
        return $this->last_count;
    }
    
    /**
     * Обновляет дату парсинга rss
     *
     * @param Rss $rss
     * @return bool
     */
    public function updateLastUpdate(Rss $rss)
    {
        return (bool)$this->prepare('UPDATE `'.$this->table.'` SET `date_last_update` = s:date WHERE `id` = i:id')
                          ->exec(array('date' => $rss->getDateLastUpdate(), 'id' => $rss->getId()));
    }
    
    /**
     * Парсинг rss
     *
     * @param int | array $what
     * @return array
     */
    public function parse($what = Rss::STATUS_ACTIVE)
    {
        $result = array();
        
        $list = $this->getList(1, 100000, $what);
        
        $newsModel = new NewsModel(DbConnection::COMMON_SPACE, true);
        
        foreach ((array)$list as $rss) {
            /* @var $rss Rss */
            $result[$rss->getUrl()] = 0;
            
            $xml = @simplexml_load_file($rss->getUrl());
            
            if ($xml && $xml instanceof SimpleXMLElement) {
                if (!empty($xml->channel) && !empty($xml->channel->item)) {
                    foreach ($xml->channel->item as $item) {
                        
                        $n = new News();
                        
                        $n->setRssId($rss->getId());
                        $n->setStatus(News::STATUS_ACTIVE); // делаем сразу активными, так как у меня пока нет редакторов :)
                        
                        $n->setLink((string)$item->link);
                        
                        if (!empty($item->guid)) {
                            $hash = md5((string)$item->guid);
                        } else {
                            $hash = md5($n->getLink());
                        }
                        
                        $title = Utils::prepareXMLString((string)$item->title);
                        
                        $n->setTitle($title);
                        $n->setDescription(Utils::prepareXMLString((string)$item->description));
                        $n->setHash($hash);

                        $n->setWordsUrl(Utils::translateStr($title));
                        
                        if (!empty($item->pubDate)) {
                            $n->setPubdate(date("Y-m-d H:i:s", strtotime((string)$item->pubDate)));
                        } else {
                            $n->setPubdate(date("Y-m-d H:i:s"));
                        }
                        
                        if (isset($item->enclosure) && $item->enclosure->attributes()) {
                            $attr = $item->enclosure->attributes();
                            if (!empty($attr['url'])) {
                                $n->setImage((string)$attr['url']);
                            }
                        }

                        if (!$newsModel->issetByHash($n->getHash())) { // новость надо добавить только если ее еще нет
                            $newsModel->add($n);
                            
                            $result[$rss->getUrl()]++;
                        }
                    }
                }
            }
            
            // обновляем дату последнего парсинга ленты
            $rss->setDateLastUpdate(date("Y-m-d H:i:s"));
            $this->updateLastUpdate($rss);
        }
        
        return $result;
    }
}
